# -*- coding: utf-8 -*-
from datetime import datetime, timedelta
import time
from openerp.tools.translate import _
import openerp.addons.decimal_precision as dp
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
from openerp.osv import fields, osv
from openerp import workflow


class sale_order(osv.osv):
    _name='sale.order'
    _inherit = ['mail.thread','ir.needaction_mixin']
    _description = u"销售订单"
    
    def _invoiced_rate(self,cursor,user,ids,name,arg,context= None):
        res= {}
        for sale in self.brows(cursor,user,ids,context= context):
            if sale.invoiced:
                res[sale.id]= 100.0
                continue 
            tot=0.0
            for invoice in sale.invoice_ids:
                if invoice.state not in ('draft','cancel',):
                    tot += invoice.amount_untaxed
            if tot:
                res[sale.id]=min(100.0,tot * 100.0/(sale.amount_ontaxed or 1.00))
            else :
                res[sale.id]= 0.0
        return res
    
    def _invoiced(self,cursor,user,ids,name,arg,context= None):
        res = {}
        for sale in self.brows(cursor,user,ids,context= context):
            res[sale.id]= True
            invoice_existence =False
            for invoice in sale.invoice_ids :
                if invoice.state != 'cancel':
                    invoice_existence= True
                    if invoice.state != 'paid':
                        res[sale.id]= False
                        break 
                    '''  如果ivoiced 不是paid状态，那么invoice返回False  '''
            if not invoice_existence or sale.state == 'manual':
                res[sale.id]= False
        return res
                    
    def _invoiced_search(self,cursor,user,obj,name,args,context= None):
        if not len(args) :
            return []
        clause = ''
        sale_clause = ''
        no_invoiced= False
        for arg in args:
            if (arg[1] == '=' and arg[2]) or (arg[1] == '!=' and not arg[2]):
                clause += 'AND inv.state = \'paid\''
            else:
                clause += 'AND inv.state != \'cancel\' AND sale.state != \'cancel\'  AND inv.state <> \'paid\'  AND rel.order_id = sale.id '
                sale_clause = ',  sale_order AS sale '
                no_invoiced = True

        cursor.execute('SELECT rel.order_id ' \
                'FROM sale_order_invoice_rel AS rel, account_invoice AS inv '+ sale_clause + \
                'WHERE rel.invoice_id = inv.id ' + clause)
        res = cursor.fetchall()
        if no_invoiced:
            cursor.execute('SELECT sale.id ' \
                    'FROM sale_order AS sale ' \
                    'WHERE sale.id NOT IN ' \
                        '(SELECT rel.order_id ' \
                        'FROM sale_order_invoice_rel AS rel) and sale.state != \'cancel\'')
            res.extend(cursor.fetchall())
        if not res:
            return [('id', '=', 0)]
        return [('id', 'in', [x[0] for x in res])]
    
    def _invoiced_exists(self,cursor,user,ids,name,arg,context= None):
        res = {}
        for sale in self.browse(cursor,user,ids,context=context):
            res[sale.id] = False
            if sale.invoice_ids:
                res[sale.id] = True
        return res
    
    def _amount_all_wrapper(self,cr,uid,ids,field_name,arg,context=None):
        '''  包装一下，避免被调用的参数直接使用function函数传递过来的参数    '''
        return self._amount_all(cr, uid, ids, field_name, arg, context)
    
    def _get_order(self,cr,uid,ids,context=None):
        result={}
        for line in self.pool.get('sale.order.line').browse(cr,uid,ids,context=context):
            result[line.order_id.id] = True
        return result.keys()
    
    def _get_default_company(self, cr, uid, context=None):
        company_id = self.pool.get('res.users')._get_company(cr, uid, context=context)
        if not company_id:
            raise osv.except_osv(_(u'错误!'), _(u'这不是当前用户默认的公司!'))
        return company_id
    
    def _get_default_section_id(self, cr, uid, context=None):
        """ Gives default section by checking if present in the context
        (通过检查存在的context，给予默认的section) """
        section_id = self._resolve_section_id_from_context(cr, uid, context=context) or False
        if not section_id:
            section_id = self.pool.get('res.users').browse(cr, uid, uid, context).default_section_id.id or False
        return section_id
    
    def _resolve_section_id_from_context(self, cr, uid, context=None):
        """ Returns ID of section based on the value of 'section_id'
            context key, or None if it cannot be resolved to a single
            Sales Team（根据关键字‘section_id’上下文的值返回销售团队的ID，如果不是一个单独的销售团队，则不返回）.
        """
        if context is None:
            context = {}
        if type(context.get('default_section_id')) in (int, long):
            return context.get('default_section_id')
        if isinstance(context.get('default_section_id'), basestring):
            section_ids = self.pool.get('crm.case.section').name_search(cr, uid, name=context['default_section_id'], context=context)
            if len(section_ids) == 1:
                return int(section_ids[0][0])
        return None
    
    _columns = {
                'name':fields.char(u'订单号',
                                   required = True,
                                   copy = False,
                                   readonly = True,
                                   states={'draft':[('readonly',False)],
                                           'sent':[('readonly',False)],
                                           },
                                   select= True
                                   ),
                'origin':fields.char(u'原单据',
                                     help=u"生成此销售单的原单据"
                                     ),
                'client_order_ref':fields.char(u'客户订单号',
                                               copy= False,
                                               ),
                'state':fields.selection([
                    ('draft',u'报价单'),
                    ('sent',u'已发送'),
                    ('cancel',u'已取消'),
                    ('waiting_date',u'排期'),
                    ('progress',u'销售订单'),
                    ('manual',u'待开票'),
                    ('shipping_except',u'发货异常'),
                    ('invoice_except',u'发票异常'),
                    ('done',u'已完成'),
                    ],
                     u'状态',readonly= True,
                              copy= False,
                              help= '给出报价和销售订单的状态，异常状态发生时自动设置取消操作，\
                              在发票的验证(发票异常)或发货单被取消(发货异常)，确认发票时设置等待进度的状态，但等待计划在订单日运行'),
                'date_order':fields.datetime(u'日期',
                                             required= True,
                                             readonly= True,
                                             select= True,
                                             states={'draft':[('readonly',False)],
                                                     'sent':[('readonly',False)]},
                                             copy= False),
                'create_date':fields.datetime(u'创建日期',
                                              readonly= True,
                                              select= True,
                                              help=u'订单被创建日期'),
                'date_confirm':fields.date(u'确认日期',
                                           readonly= True,
                                           select= True,
                                           help='订单被确认日期',
                                           copy= False),
                'user_id':fields.many2one('res.users',u'销售人员',
                                          readonly= True,
                                          states={'draft':[('readonly',False)],
                                                  'sent':[('readonly',False)]},
                                          select= True,
                                          track_visibility= 'onchange',
                                          ),
                'partner_id':fields.many2one('res.partner',u'客户',
                                             readonly= True,
                                             states= {'draft':[('readonly',False)],
                                                     'sent':[('readonly',False)]},
                                             required= True,
                                             change_defult= True,
                                             select= True,
                                             track_visibility= 'always'),
                'partner_invoice_id':fields.many2one('res.partner',u'客户发票地址',
                                                     readonly= True,
                                                     required= True,
                                                     states= {'draft':[('readonly',False)],
                                                              'sent':[('readonly',False)]},
                                                     help='当前的销售订单的发票地址',
                                                     ),
                'partner_shipping_id':fields.many2one('res.partner',u'发货地址',
                                                      readonly= True,
                                                      required= True,
                                                      states= {'draft':[('readonly',False)],
                                                               'sent':[('readonly',False)]},
                                                      help='当前的销售订单的送货地址',
                                                      ),
                'order_policy':fields.selection([('manual',u'按需求开票'),],
                                                u'创建发票',
                                                readonly= True,
                                                required= True,
                                                states= {'draft':[('readonly',False)],
                                                         'sent':[('readonly',False)]},
                                                help='此字段控制发票和发货的先后顺序'
                                                ),
                'pricelist_id':fields.many2one('product.pricelist',u'价格表',
                                               readonly= True,
                                               required= True,
                                               states= {'draft':[('readonly',False)],
                                                        'sent':[('readonly',False)]},
                                               help='当前销售订单的价格表',
                                               ),
                'currency_id':fields.related('pricelist_id','currency_id',
                                             type='many2one',
                                             relation='res.currency',
                                             string= u'货币',
                                             readonly= True,
                                             required= True,
                                             ),
                'project_id':fields.many2one('account.analytic.account',u'合同/分析',
                                             readonly= True,
                                             states= {'draft':[('readonly',False)],
                                                      'sent':[('readonly',False)]},
                                             help='当前销售订单的协议分析',
                                              ),
                  'order_line':fields.one2many('sale.order.line','order_id',u'订单行',
                                               readonly= True,
                                               states= {'draft':[('readonly',False)],
                                                        'sent':[('readonly',False)]},
                                               copy= True,
                                               ),
                'invoice_ids':fields.many2many('account.invoice',
                                               'sale_order_invoice_rel',
                                               'order_id',
                                               'invoice_id',
                                               u'发票',
                                               readonly= True,
                                               copy= False,
                                               help= '这销售订单生成的发票列表，同一销售订单可能生成几次发票',
                                               ),
                'invoiced_rate':fields.function(_invoiced_rate,
                                                string=u'税率',
                                                type= 'float',
                                                ),
                'invoiced':fields.function(_invoiced,
                                           string= u'支付',
                                           fnct_search=_invoiced_search,
                                           type='boolean',
                                           help=u'该订单所有发票已支付',
                                           ),
                'invoice_exists':fields.function(_invoiced_exists,string=u'发票',
                                                 fnct_search= _invoiced_search,
                                                 type= 'boolean',
                                                 help= '销售订单至少有一个发票'),
                'note':fields.text(u'合同条款'),
                'amount_untaxed':fields.function(_amount_all_wrapper,
                                                digitx_compute = dp.get_precision(u'账户'),
                                                string=u'免税金额',
                                                store={
                                                       'sale.order':(lambda self,cr,uid,ids,c={}:ids,['order_line'],10),
                                                       'sale.order.line':(_get_order,['price_unit',
                                                                                      'tax_id','discount',
                                                                                      'product_uom_qty'],10)
                                                       },
                                                multi='sums',
                                                help=u'不含税金额',
                                                track_visibility='always'
                                                ),
                 'amount_tax':fields.function(_amount_all_wrapper,
                                                digitx_compute = dp.get_precision(u'账户'),
                                                string=u'税金',
                                                store={
                                                       'sale.order':(lambda self,cr,uid,ids,c={}:ids,['order_line'],10),
                                                       'sale.order.line':(_get_order,['price_unit',
                                                                                      'tax_id','discount',
                                                                                      'product_uom_qty'],10)
                                                       },
                                                multi='sums',
                                                help=u'纳税额',
                                                ),
                 'amount_total':fields.function(_amount_all_wrapper,
                                                digitx_compute = dp.get_precision(u'账户'),
                                                string=u'总额',
                                                store={
                                                       'sale.order':(lambda self,cr,uid,ids,c={}:ids,['order_line'],10),
                                                       'sale.order.line':(_get_order,['price_unit',
                                                                                      'tax_id','discount',
                                                                                      'product_uom_qty'],10)
                                                       },
                                                multi='sums',
                                                help=u'总金额',
                                                ),
                'payment_term':fields.many2one('account.payment.term',u'付款期限'),
                'fiscal_position':fields.many2one('account.fiscal.position',u'财政状况'),
                'company_id':fields.many2one('res.company',u'公司'),
                'section_id':fields.many2one('crm.case.section',u'销售团队'),
                'procurement_group_id':fields.many2one('procurement.group',u'补货组',copy=False),
                'product_id':fields.related('orde_line','product_id',type='many2one',
                                            relation='product.product',string=u'产品'),               
                }
    
    _defaults = {
        'date_order': fields.datetime.now,
        'order_policy': 'manual',
        'company_id': _get_default_company,
        'state': 'draft',
        'user_id': lambda obj, cr, uid, context: uid,
        'name': lambda obj, cr, uid, context: '/',
        'partner_invoice_id': lambda self, cr, uid, context: context.get('partner_id', False) and self.pool.get('res.partner').address_get(cr, uid, [context['partner_id']], ['invoice'])['invoice'],
        'partner_shipping_id': lambda self, cr, uid, context: context.get('partner_id', False) and self.pool.get('res.partner').address_get(cr, uid, [context['partner_id']], ['delivery'])['delivery'],
        'note': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.sale_note,
        'section_id': lambda s, cr, uid, c: s._get_default_section_id(cr, uid, c),
    }
    
    def print_quotation(self, cr, uid, ids, context=None):
        '''  这个函数打印报价单，并将它标记为发送 ，使我们可以更容易的看到工作流的下一步  '''
        assert len(ids) == 1, '此选项用于只存在一个id的情况'
        self.signal_workflow(cr,uid,ids,'quotation_sent')
        return self.pool['report'].get_action(cr,uid,ids,'sale.report_saleorder',context=context)
    
    def action_button_confirm(self, cr, uid, ids, context=None):
        assert len(ids) == 1, '此选项用于只存在一个ID的情况'
        self.signal_workflow(cr, uid, ids, 'order_confirm')
        return True
    
    def action_view_invoice(self, cr, uid, ids, context=None):
        '''  这个函数为销售订单生成一个发票，无论是从列表
        This function returns an action that display existing invoices of given sales order ids. 
        It can either be a in a list or in a form view, if there is only one invoice to show.''' 
        mod_obj = self.pool.get('ir.model.data')
        act_obj = self.pool.get('ir.actions.act_window')

        result = mod_obj.get_object_reference(cr, uid, 'account', 'action_invoice_tree1')
        id = result and result[1] or False
        result = act_obj.read(cr, uid, [id], context=context)[0]
        #compute the number of invoices to display
        inv_ids = []
        for so in self.browse(cr, uid, ids, context=context):
            inv_ids += [invoice.id for invoice in so.invoice_ids]
        #choose the view_mode accordingly
        if len(inv_ids)>1:
            result['domain'] = "[('id','in',["+','.join(map(str, inv_ids))+"])]"
        else:
            res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_form')
            result['views'] = [(res and res[1] or False, 'form')]
            result['res_id'] = inv_ids and inv_ids[0] or False
        return result
    
    
    def action_quotation_send(self,cr,uid,ids,context=None):
        '''  这个功能可以打开一个窗口，撰写邮件，默认加载edi销售模板的消息'''
        assert len(ids) == 1,'此选项用于只存在一个id的情况'
        ir_model_data=self.pool.get('ir.model.data')
        try:
            template_id = ir_model_data.get_object_reference(cr,uid,'sale','email_template_edi_sale')[1]
        except ValueError:
            template_id = False
        try:
            compose_form_id = ir_model_data.get_object_reference(cr,uid,'mail','email_compose_message_wizard_form')[1]
        except ValueError:
            compose_form_id = False
            ctx = dict()
            ctx.update({
                        'default_model':'sale.order',
                        'default_res_id':ids[0],
                        'default_use_template':bool(template_id),
                        'default_template_id':template_id,
                        'default_composition_mode':'comment',
                        'mark_so_as_send':True,
                        })
        return {
                'type':'ir.actions.act_window',
                'view_type':'form',
                'view_model':'form',
                'res_order':'mail.compose.message',
                'views':[(compose_form_id,'form')],
                'view_id':compose_form_id,
                'target':'new',
                'context':ctx,
                }
        
    def copy_quotation(self, cr, uid, ids, context=None):
        '''此函数用于复制一个报价单'''
        id = self.copy(cr, uid, ids[0], context=context)
        view_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sale', 'view_order_form')
        view_id = view_ref and view_ref[1] or False,
        return {
            'type': 'ir.actions.act_window',
            'name': _('Sales Order'),
            'res_model': 'sale.order',
            'res_id': id,
            'view_type': 'form',
            'view_mode': 'form',
            'view_id': view_id,
            'target': 'current',
            'nodestroy': True,
        }
        
    def action_cancel(self, cr, uid, ids, context=None):
        '''此函数用于取消销售订单'''
        if context is None:
            context = {}
        sale_order_line_obj = self.pool.get('sale.order.line')
        account_invoice_obj = self.pool.get('account.invoice')
        for sale in self.browse(cr, uid, ids, context=context):
            for inv in sale.invoice_ids:
                if inv.state not in ('draft', 'cancel'):
                    raise osv.except_osv(
                        _(u'不能取消这个销售订单!'),
                        _(u'请先取消连接此销售订单的发票'))
                inv.signal_workflow('invoice_cancel')
            sale_order_line_obj.write(cr, uid, [l.id for l in  sale.order_line],
                    {'state': 'cancel'})
        self.write(cr, uid, ids, {'state': 'cancel'})
        return True
    
    def onchange_pricelist_id(self, cr, uid, ids, pricelist_id, order_lines, context=None):
        '''  客户修改时价格表变化，订单行被清空再修改客户弹警告窗口 返回不同的ruturn   '''
        context = context or {}
        if not pricelist_id:
            return {}
        value = {
            'currency_id': self.pool.get('product.pricelist').browse(cr, uid, pricelist_id, context=context).currency_id.id
        }
        if not order_lines or order_lines == [(6, 0, [])]:
            return {'value': value}
        warning = {
            'title': _(u'价目表警告!'),
            'message' : _(u'如果更改此订单的价目表（最终的货币），现有的订单行的价格将不会更新.')
        }
        return {'warning': warning, 'value': value}
    
    def get_salenote(self, cr, uid, ids, partner_id, context=None):
        '''  获得销售笔记 (链接onchange_partner_id) '''
        context_lang = context.copy() 
        if partner_id:
            partner_lang = self.pool.get('res.partner').browse(cr, uid, partner_id, context=context).lang
            context_lang.update({'lang': partner_lang})
        return self.pool.get('res.users').browse(cr, uid, uid, context=context_lang).company_id.sale_note
    
    def onchange_delivery_id(self, cr, uid, ids, company_id, partner_id, delivery_id, fiscal_position, context=None):
        '''  交货的onchange ID（链接onchange_partner_id）  '''
        r = {'value': {}}
        if not fiscal_position:
            if not company_id:
                company_id = self._get_default_company(cr, uid, context=context)
            fiscal_position = self.pool['account.fiscal.position'].get_fiscal_position(cr, uid, company_id, partner_id, delivery_id, context=context)
            if fiscal_position:
                r['value']['fiscal_position'] = fiscal_position
        return r
    

    
    def onchange_partner_id(self, cr, uid, ids, part, context=None):
        '''  客户的 onchange ID'''
        if not part:
            return {'value': {'partner_invoice_id': False, 'partner_shipping_id': False,  'payment_term': False, 'fiscal_position': False}}

        part = self.pool.get('res.partner').browse(cr, uid, part, context=context)
        addr = self.pool.get('res.partner').address_get(cr, uid, [part.id], ['delivery', 'invoice', 'contact'])
        pricelist = part.property_product_pricelist and part.property_product_pricelist.id or False
        payment_term = part.property_payment_term and part.property_payment_term.id or False
        dedicated_salesman = part.user_id and part.user_id.id or uid
        val = {
            'partner_invoice_id': addr['invoice'],
            'partner_shipping_id': addr['delivery'],
            'payment_term': payment_term,
            'user_id': dedicated_salesman,
        }
        delivery_onchange = self.onchange_delivery_id(cr, uid, ids, False, part.id, addr['delivery'], False,  context=context)
        val.update(delivery_onchange['value'])
        if pricelist:
            val['pricelist_id'] = pricelist
        sale_note = self.get_salenote(cr, uid, ids, part.id, context=context)
        if sale_note: val.update({'note': sale_note})  
        return {'value': val}
    
    def _prepare_invoice(self, cr, uid, order, lines, context=None):
        """Prepare the dict of values to create the new invoice for a
           sales order. This method may be overridden to implement custom
           invoice generation (making sure to call super() to establish
           a clean extension chain).

           :param browse_record order: sale.order record to invoice
           :param list(int) line: list of invoice line IDs that must be
                                  attached to the invoice
           :return: dict of value to create() the invoice
        """
        if context is None:
            context = {}
        journal_ids = self.pool.get('account.journal').search(cr, uid,
            [('type', '=', 'sale'), ('company_id', '=', order.company_id.id)],
            limit=1)
        if not journal_ids:
            raise osv.except_osv(_('Error!'),
                _('Please define sales journal for this company: "%s" (id:%d).') % (order.company_id.name, order.company_id.id))
        invoice_vals = {
            'name': order.client_order_ref or '',
            'origin': order.name,
            'type': 'out_invoice',
            'reference': order.client_order_ref or order.name,
            'account_id': order.partner_id.property_account_receivable.id,
            'partner_id': order.partner_invoice_id.id,
            'journal_id': journal_ids[0],
            'invoice_line': [(6, 0, lines)],
            'currency_id': order.pricelist_id.currency_id.id,
            'comment': order.note,
            'payment_term': order.payment_term and order.payment_term.id or False,
            'fiscal_position': order.fiscal_position.id or order.partner_id.property_account_position.id,
            'date_invoice': context.get('date_invoice', False),
            'company_id': order.company_id.id,
            'user_id': order.user_id and order.user_id.id or False,
            'section_id' : order.section_id.id
        }

        # Care for deprecated _inv_get() hook - FIXME: to be removed after 6.1
        invoice_vals.update(self._inv_get(cr, uid, order, context=context))
        return invoice_vals
    
    def button_dummy(self, cr, uid, ids, context=None):
        return True
    
    def onchange_fiscal_position(self, cr, uid, ids, fiscal_position, order_lines, context=None):
        '''Update taxes of order lines for each line where a product is defined
                    （执行命令时，对每一个详细产品更新税款）
        :param（参数） list ids: not used
        :param int fiscal_position: sale order fiscal position（销售订单的财政状况）
        :param list order_lines: command list for one2many write method（为列表写one2many的方法）
        '''
        order_line = []
        fiscal_obj = self.pool.get('account.fiscal.position')
        product_obj = self.pool.get('product.product')
        line_obj = self.pool.get('sale.order.line')

        fpos = False
        if fiscal_position:
            fpos = fiscal_obj.browse(cr, uid, fiscal_position, context=context)
        
        for line in order_lines:
            # create    (0, 0,  { fields })
            # update    (1, ID, { fields })
            if line[0] in [0, 1]:
                prod = None
                if line[2].get('product_id'):
                    prod = product_obj.browse(cr, uid, line[2]['product_id'], context=context)
                elif line[1]:
                    prod =  line_obj.browse(cr, uid, line[1], context=context).product_id
                if prod and prod.taxes_id:
                    line[2]['tax_id'] = [[6, 0, fiscal_obj.map_tax(cr, uid, fpos, prod.taxes_id)]]
                order_line.append(line)

            # link      (4, ID)
            # link all  (6, 0, IDS)
            elif line[0] in [4, 6]:
                line_ids = line[0] == 4 and [line[1]] or line[2]
                for line_id in line_ids:
                    prod = line_obj.browse(cr, uid, line_id, context=context).product_id
                    if prod and prod.taxes_id:
                        order_line.append([1, line_id, {'tax_id': [[6, 0, fiscal_obj.map_tax(cr, uid, fpos, prod.taxes_id)]]}])
                    else:
                        order_line.append([4, line_id])
            else:
                order_line.append(line)
        return {'value': {'order_line': order_line}}

    
class sale_order_line(osv.osv):
    _name='sale.order.line'
    _description='销售订单明细'
    
    def _fnct_line_invoiced(self,cr,uid,ids,field_name,args,context=None):
        res = dict.fromkeys(ids, False)
        for this in self.browse(cr, uid, ids, context=context):
            res[this.id] = this.invoice_lines and \
                all(iline.invoice_id.state != 'cancel' for iline in this.invoice_lines) 
        return res

    def _order_line_from_invoice(self, cr, uid, ids, context=None):
        '''  为了实现ACL-wise访问m2m表更为省力  '''
        cr.execute("""SELECT DISTINCT sol.id FROM sale_order_invoice_rel rel JOIN
                                                  sale_order_line sol ON (sol.order_id = rel.order_id)
                                    WHERE rel.invoice_id = ANY(%s)""", (list(ids),))
        return [i[0] for i in cr.fetchall()]
    
    def _amount_line(self, cr, uid, ids, field_name, arg, context=None):
        tax_obj = self.pool.get('account.tax')
        cur_obj = self.pool.get('res.currency')
        res = {}
        if context is None:
            context = {}
        for line in self.browse(cr, uid, ids, context=context):
            price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
            taxes = tax_obj.compute_all(cr, uid, line.tax_id, price, line.product_uom_qty,
                                        line.product_id, line.order_id.partner_id)
            cur = line.order_id.pricelist_id.currency_id
            res[line.id] = cur_obj.round(cr, uid, cur, taxes['total'])
        return res

        
    
    _columns={
              'order_id':fields.many2one('sale.order',
                                           u'订单号',
                                           required=True,
                                           ondelete='cascade',
                                           select=True,
                                           readonly=True,
                                           states={'draft':[('readonly',False)]}
                                           ),
              'name':fields.text('description',
                                 reqired=True,
                                 readonly=True,
                                 states={'draft':[('readonly',False)]},
                                 ),
              'sequence':fields.integer(u'序列',
                                        help='在销售订单行列表时显示排列顺序',
                                        ),
              'product_id':fields.many2one('product.product',
                                          u'产品',
                                          domain="[('sale_ok','=',True)]",
                                          change_defults=True,
                                          readonly=True,
                                          states={'draft':[('readonly',False)]},
                                          ondelete='restrict',
                                          ),
              'invoice_lines':fields.many2many('account.invoice.line',
                                               'sale_order_line_invoice_rel',
                                               'order_line_id',
                                               'invoice_id',
                                               u'发票明细',
                                               readonly=True,
                                               copy=False,
                                               ),
              'invoice':fields.function(_fnct_line_invoiced,
                                        string=u'发票',
                                        type='boolean',
                                        store={'account.invoice':(_order_line_from_invoice,['state'],10),
                                               'sale.order.line':(lambda self,cr,uid,ids,ctx=None:ids,['invoice_lines'],10),
                                               }
                                        ),
              'price_unit': fields.float(u'单价', required=True, 
                                        digits_compute= dp.get_precision('Product Price'), 
                                        readonly=True, 
                                        states={'draft': [('readonly', False)]}
                                         ),
              'price_subtotal': fields.function(_amount_line, string='价格合计', 
                                               digits_compute= dp.get_precision('Account')),
              'tax_id': fields.many2many('account.tax', 'sale_order_tax', 
                                          'order_line_id', 
                                          'tax_id', u'税费', readonly=True,
                                           states={'draft': [('readonly', False)]}),
              'address_allotment_id': fields.many2one('res.partner', 'Allotment Partner',
                                                       help="特定的产品分配给特定的小伙伴"),
              'product_uom_qty': fields.float(u'数量', digits_compute= dp.get_precision('Product UoS'),
                                               required=True, 
                                               readonly=True, 
                                               states={'draft': [('readonly', False)]}),
              'product_uom': fields.many2one('product.uom', u'计量单位 ', 
                                             required=True, 
                                             readonly=True, 
                                             states={'draft': [('readonly', False)]}),
              'product_uos_qty': fields.float(u'数量(UoS)' ,digits_compute= dp.get_precision('Product UoS'),
                                               readonly=True, 
                                               states={'draft': [('readonly', False)]}),
              'product_uos': fields.many2one('product.uom', '销售单位Product UoS'),
              'discount': fields.float(u'折扣 (%)', digits_compute= dp.get_precision('Discount'), 
                                       readonly=True, 
                                       states={'draft': [('readonly', False)]}),
              'th_weight': fields.float(u'权重', 
                                        readonly=True, 
                                        states={'draft': [('readonly', False)]}),
              'state': fields.selection([('cancel', u'取消'),
                                         ('draft', u'草稿'),
                                         ('confirmed', u'确认'),
                                         ('exception', u'异常'),
                                         ('done', u'完成')],
                                          'Status', required=True, readonly=True, copy=False,
                                         help=u'cancel,设置状态当用户取消销售订单时\
                                                draft,处于报价单状态相关的销售订单\
                                                confirmed,当相关销售订单确认状态时\
                                                exception,当相关销售订单被设定为异常状态时\
                                                done,当销售订单行已完成（pick?）状态设置 \ '
                                        ),
              'order_partner_id': fields.related('order_id', 'partner_id',
                                                  type='many2one',
                                                  relation='res.partner', 
                                                  store=True, string=u'客户'),
              'salesman_id':fields.related('order_id', 'user_id',
                                            type='many2one',
                                             relation='res.users', 
                                             store=True, string=u'销售员'),
               'company_id': fields.related('order_id', 'company_id', 
                                            type='many2one', 
                                            relation='res.company', 
                                            string=u'公司', 
                                            store=True, readonly=True),
              'delay': fields.float(u'交货时间', required=True,
                                     help=u"订单确认和发货的产品给客户之间的天数",
                                     readonly=True, 
                                     states={'draft': [('readonly', False)]}),
              'procurement_ids': fields.one2many('procurement.order', 
                                                 'sale_line_id', u'采购'),             
              }
    
    def product_id_change(self,cr,uid,ids,pricelist,product,qty=0,uom=False,qty_uos=0,uos=False,
                          name='',partner_id=False,lang=False,update_tax=True,date_order=False,
                          packaging=False,fiscal_position=False,flag=False,context=None):
        context=context or {}
        lang=lang or context.get('lang',False)
        if not partner_id:
            raise osv.except_osv(_('没有客户！'),_('选择产品之前需选择一个客户'))
        warning=False
        product_uom_obj=self.pool.get('product.uom')
        partner_obj=self.pool.get('res.partner')
        product_obj=self.pool.get('product.product')
        context = {'lang': lang, 'partner_id': partner_id}
        partner=partner_obj.browse(cr,uid,partner_id)
        lang = partner.lang
        context_partner={'lang':lang,'partner_id':partner_id}
        
        if not product:
            return {'value':{'the_weight':0,
                             'product_uos_qty':qty},'domain':{'product_uom':[],'product_uos':[]}}
        if not date_order:
            date_order=time.strftime(DEFAULT_SERVER_DATE_FORMAT)
            
        result={}
        warning_msgs=''
        product_obj=product_obj.browse(cr,uid,product,context=context_partner)
        
        uom2=False
        if uom:
            uom2=product_uom_obj.browse(cr,uid,uom)
            if product_obj.uom_id.category_id.id != uom2.category_id.id:
                uom=False
        if uos:
            if product_obj.uos_id:
                uos2=product_uom_obj.browse(cr,uid,uos)
                if product_obj.uos_id.category_id.id != uos2.category_id.id:
                    uos=False
            else:
                 uos=False
            
        fpos = False
        if not fiscal_position:
            fpos=partner.property_account_position or False
        else : 
            fpos=self.pool.get('account.fiscal.position').browse(cr,uid,fiscal_position)
        if update_tax: #只改变了数量
            result['tax_id'] = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, product_obj.taxes_id)

        if not flag:
            result['name'] = self.pool.get('product.product').name_get(cr, uid, [product_obj.id], context=context_partner)[0][1]
            if product_obj.description_sale:
                result['name'] += '\n'+product_obj.description_sale
        domain = {}
        if (not uom) and (not uos):
            result['product_uom'] = product_obj.uom_id.id
            if product_obj.uos_id:
                result['product_uos'] = product_obj.uos_id.id
                result['product_uos_qty'] = qty * product_obj.uos_coeff
                uos_category_id = product_obj.uos_id.category_id.id
            else:
                result['product_uos'] = False
                result['product_uos_qty'] = qty
                uos_category_id = False
            result['th_weight'] = qty * product_obj.weight
            domain = {'product_uom':
                        [('category_id', '=', product_obj.uom_id.category_id.id)],
                        'product_uos':
                        [('category_id', '=', uos_category_id)]}
        elif uos and not uom: # only happens if uom is False（只能在uom错误时产生）
            result['product_uom'] = product_obj.uom_id and product_obj.uom_id.id
            result['product_uom_qty'] = qty_uos / product_obj.uos_coeff
            result['th_weight'] = result['product_uom_qty'] * product_obj.weight
        elif uom: # whether uos is set or not（uos是否存在）
            default_uom = product_obj.uom_id and product_obj.uom_id.id
            q = product_uom_obj._compute_qty(cr, uid, uom, qty, default_uom)
            if product_obj.uos_id:
                result['product_uos'] = product_obj.uos_id.id
                result['product_uos_qty'] = qty * product_obj.uos_coeff
            else:
                result['product_uos'] = False
                result['product_uos_qty'] = qty
            result['th_weight'] = q * product_obj.weight        # Round the quantity up（做了几个步骤？）

        if not uom2:
            uom2 = product_obj.uom_id
        # get unit price（获得单价）

        if not pricelist:
            warn_msg = _('你必须选择一个价目表或客户在销售单中 !\n'
                    '在选择产品之前设置一个.')
            warning_msgs += _("没有价格表 ! : ") + warn_msg +"\n\n"
        else:
            price = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist],
                    product, qty or 1.0, partner_id, {
                        'uom': uom or result.get('product_uom'),
                        'date': date_order,
                        })[pricelist]
            if price is False:
                warn_msg = _("找不到价目表来匹配这个产品和数量.\n"
                        "你必须改变一下，无论是产品，数量或价格表.")

                warning_msgs += _("没发现有效的价目表 ! :") + warn_msg +"\n\n"
            else:
                result.update({'price_unit': price})
        if warning_msgs:
            warning = {
                       'title': _('配置错误!'),
                       'message' : warning_msgs
                    }
        return {'value': result, 'domain': domain, 'warning': warning}
    
    def product_uom_change(self, cursor, user, ids, pricelist, product, qty=0,
            uom=False, qty_uos=0, uos=False, name='', partner_id=False,
            lang=False, update_tax=True, date_order=False, context=None):
        context = context or {}
        lang = lang or ('lang' in context and context['lang'])
        if not uom:
            return {'value': {'price_unit': 0.0, 'product_uom' : uom or False}}
        return self.product_id_change(cursor, user, ids, pricelist, product,
                qty=qty, uom=uom, qty_uos=qty_uos, uos=uos, name=name,
                partner_id=partner_id, lang=lang, update_tax=update_tax,
                date_order=date_order, context=context)
        
class account_invoice(osv.Model):
    _inherit = 'account.invoice'

    def _get_default_section_id(self, cr, uid, context=None):
        """ Gives default section by checking if present in the context
        (通过检查存在的context，给予默认的section)  """
        section_id = self._resolve_section_id_from_context(cr, uid, context=context) or False
        if not section_id:
            section_id = self.pool.get('res.users').browse(cr, uid, uid, context).default_section_id.id or False
        return section_id

    def _resolve_section_id_from_context(self, cr, uid, context=None):
        """ Returns ID of section based on the value of 'section_id'
            context key, or None if it cannot be resolved to a single
            Sales Team.
            （根据关键字‘section_id’上下文的值返回销售团队的ID，如果不是一个单独的销售团队，则不返回）
        """
        if context is None:
            context = {}
        if type(context.get('default_section_id')) in (int, long):
            return context.get('default_section_id')
        if isinstance(context.get('default_section_id'), basestring):
            section_ids = self.pool.get('crm.case.section').name_search(cr, uid, name=context['default_section_id'], context=context)
            if len(section_ids) == 1:
                return int(section_ids[0][0])
        return None

    _columns = {
        'section_id': fields.many2one('crm.case.section', 'Sales Team'),
    }

    _defaults = {
        'section_id': lambda self, cr, uid, c=None: self._get_default_section_id(cr, uid, context=c)
    }
    
    
class procurement_order(osv.osv):
    _inherit = 'procurement.order'
    _columns = {
        'sale_line_id': fields.many2one('sale.order.line', string=u'销售订单详细'),
    }